﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace 屏幕截图工具
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.UserPaint, true);
            //SetStyle(ControlStyles.UserPaint | ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer,true);
        }

        bool IsUp = false;
        bool IsLeft = false;

        #region 基本设置参数  
        /// <summary>  
        /// 截图时是否显示截图信息栏  
        /// </summary>  
        public bool InfoBoxVisible = true;
        /// <summary>  
        /// 截图时是否显示编辑工具栏  
        /// </summary>  
        public bool ToolBoxVisible = true;
        /// <summary>  
        /// 截图中是否包含鼠标指针形状  
        /// </summary>  
        public bool IsCutCursor = true;
        /// <summary>  
        /// 截图时是否显示放大镜  
        /// </summary>  
        public bool ZoomBoxVisible = true;
        /// <summary>  
        /// 放大镜的尺寸——宽度  
        /// </summary>  
        public int ZoomBoxWidth = 120;
        /// <summary>  
        /// 放大镜的尺寸——高度  
        /// </summary>  
        public int ZoomBoxHeight = 100;
        #endregion

        #region 图片上传参数  
        public string PicDescFieldName = "pictitle";
        public string ImageFieldName = "upfile";
        public string PicDesc = "cutImage";
        public string UploadUrl = "http://";
        public bool DoUpload = false;
        #endregion

        #region 自动保存参数  
        /// <summary>  
        /// 是否自动保存到硬盘  
        /// </summary>  
        public bool AutoSaveToDisk = false;
        /// <summary>  
        /// 自动保存目录  
        /// </summary>  
        public string AutoSaveDirectory = string.Empty;
        /// <summary>  
        /// 是否启用日期格式“2013_02_22”的子目录  
        /// </summary>  
        public bool AutoSaveSubDir = false;
        /// <summary>  
        /// 自动保存文件名前缀  
        /// </summary>  
        public string AutoSaveFileName1 = "屏幕截图";
        /// <summary>  
        /// 自动文件名规则：日期时间，日期_序号，序号  
        /// </summary>  
        public string AutoSaveFileName2 = "日期时间";
        /// <summary>  
        /// 自动保存文件格式：.png, .jpg, .jpeg, .gif, .bmp  
        /// </summary>  
        public string AutoSaveFileName3 = ".png";
        /// <summary>  
        /// 自动保存文件名序号  
        /// </summary>  
        public int autoSaveFileIndex = 0;
        #endregion 自动保存参数  

        /// <summary>
        /// 热键ID
        /// </summary>
        public int hotKeyID = 100;

        /// <summary>
        /// 热键模式:0=Ctrl+Alt+A 1=Ctrl+Shift+A
        /// </summary>
        public int HotKeyMode = 1;

        /// <summary>  
        /// 记录鼠标上一次移动的时间  
        /// </summary>  
        private long lastMouseMoveTime = System.DateTime.Now.Ticks;

        /// <summary>
        /// 控制键类型
        /// </summary>
        public enum KeyModifiers:uint
        {
            None=0,
            Alt=1,
            Control=2,
            Shift=4,
            Window=8
        }

        /// <summary>
        /// 更新UI的模式，用于标记哪些现实哪些隐藏
        /// </summary>
        [FlagsAttribute]
        public enum UpdateUIMode:uint
        {
            None=0,
            ShowTextPro=1,
            ShowPenStyle=2,
            ShowToolBox=4,
            ShowInfoBox=8,
            ShowZoomBox=16,
            ShowCutImage=32,
            HideTextPro=64,
            HidePenStyle=128,
            HidToolBox=256,
            HideInfoBox=512
        }

        /// <summary>  
        /// 更新截图信息显示框，截图编辑工具框  
        /// </summary>  
        private void UpdateCutInfoLabel(UpdateUIMode updateUIMode) // UpdateUIMode updateUIMode = UpdateUIMode.None  
        {
            //大于300毫秒或有组件显示或隐藏才进行重绘  
            long mouseMoveTimeStep = System.DateTime.Now.Ticks - lastMouseMoveTime;
            if (mouseMoveTimeStep < 30 && updateUIMode == UpdateUIMode.None) { return; }
            lastMouseMoveTime = System.DateTime.Now.Ticks;

            if (this.lbl_CutImage.Visible || (updateUIMode & UpdateUIMode.ShowCutImage) != UpdateUIMode.None)
            {
                this.lbl_CutImage.SetBounds(this.cutImageRect.Left, this.cutImageRect.Top, this.cutImageRect.Width, this.cutImageRect.Height, BoundsSpecified.All);
                if (!this.lbl_CutImage.Visible)
                {
                    this.lbl_CutImage.Show();
                }
            }
        }

        /// <summary>
        /// 是否开始截图
        /// </summary>
        private bool isCuting;
        /// <summary>
        /// 鼠标按下的点
        /// </summary>
        private Point begainPoint;
        /// <summary>
        /// 最终绘制的点
        /// </summary>
        private Point endPoint;
        /// <summary>
        /// 记录截图区域大小
        /// </summary>
        private Rectangle cutImageRect = new Rectangle(0, 0, 5, 5);

        /// <summary>
        /// 用于保存整个屏幕的图片
        /// </summary>
        protected Bitmap screenImage;


        /// <summary>
        /// 将当前屏幕的图像保存为位图同时赋值为窗体背景
        /// </summary>
        protected void ShowForm()
        {
            if (this.Visible)
            {
                this.Hide();
            }
            else
            {
                //获取当前屏幕保存到位图
                Bitmap bkImage = new Bitmap(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height);

                Graphics g = Graphics.FromImage(bkImage);
                g.CopyFromScreen(new Point(0, 0), new Point(0, 0), Screen.AllScreens[0].Bounds.Size, CopyPixelOperation.SourceCopy);

                screenImage = (Bitmap)bkImage.Clone();

                g.FillRectangle(new SolidBrush(Color.FromArgb(64, Color.Gray)), Screen.PrimaryScreen.Bounds);
                this.BackgroundImage = bkImage;

                this.ShowInTaskbar = false;
                this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
                this.Width = Screen.PrimaryScreen.Bounds.Width;
                this.Height = Screen.PrimaryScreen.Bounds.Height;
                this.Location = Screen.PrimaryScreen.Bounds.Location;

                this.WindowState = FormWindowState.Maximized;
                this.Show();
            }
        }

        /// <summary>
        /// 重写窗体消息
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            const int WM_HOTKEY = 0x0312;

            switch(m.Msg)
            {
                case WM_HOTKEY:
                    ShowForm();
                    break;
                default:
                    break;
            }

            base.WndProc(ref m);
        }

        /// <summary>
        /// 重写按键消息
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="keyData"></param>
        /// <returns></returns>
        protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData)
        {
            int WM_KEYDOWN = 256;
            int WM_SYSKEYDOWN = 260;

            if (msg.Msg == WM_KEYDOWN | msg.Msg == WM_SYSKEYDOWN)
            {
                switch (keyData)
                {
                    case Keys.Escape:
                        //this.Close();
                        Application.Exit();
                        break;
                }

            }
            return false;
        }

        /// <summary>
        /// 计算并保存截图区域框大小
        /// </summary>
        /// <param name="beginPoint"></param>
        /// <param name="endPoint"></param>
        private void SaveCutImageSize(Point beginPoint, Point endPoint)
        {
            Point currPoint = new Point(begainPoint.X,begainPoint.Y);

            if (endPoint.X < begainPoint.X)
            {
                currPoint.X = endPoint.X;
            }

            if (endPoint.Y < beginPoint.Y)
            {
                currPoint.Y = endPoint.Y;
            }


            int imgWidth = Math.Abs(beginPoint.X - endPoint.X);
            int imgHeight = Math.Abs(beginPoint.Y - endPoint.Y);

            this.cutImageRect = new Rectangle(currPoint,new Size(imgWidth, imgHeight));
        }

        /// <summary>
        /// 保存截图到剪切板
        /// </summary>
        /// <param name="saveToDisk"></param>
        /// <param name="uploadImage"></param>
        private void ExecCutImage(bool saveToDisk,bool uploadImage)
        {
            if (!this.lbl_CutImage.Visible)
                return;

            Rectangle srcRect = new Rectangle();
            srcRect.X = this.lbl_CutImage.Location.X + 2;
            srcRect.Y = this.lbl_CutImage.Location.Y + 2;
            srcRect.Width = this.lbl_CutImage.Width - 4;
            srcRect.Height = this.lbl_CutImage.Height - 4;

            Rectangle destRect = new Rectangle(0, 0, srcRect.Width, srcRect.Height);
            Bitmap bmp = new Bitmap(srcRect.Width, srcRect.Height);
            Graphics g = Graphics.FromImage(bmp);
            g.DrawImage(this.screenImage, destRect, srcRect, GraphicsUnit.Pixel);

            Clipboard.SetImage(bmp);

            ExitCutImage(true);
        }

        /// <summary>
        /// 退出截图操作
        /// </summary>
        /// <param name="hideWindow"></param>
        private void ExitCutImage(bool hideWindow)
        {
            this.lbl_CutImage.Visible = false;
            this.isCuting = false;

            if(hideWindow)
            {
                this.screenImage.Dispose();
                this.Hide();
            }
        }

        /// <summary>
        /// 窗体加载注册热键
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            //将快捷菜单绑定到小图标
            notifyIcon1.ContextMenuStrip = contextMenuStrip1;

            //隐藏窗体
            this.Hide();
            //隐藏lbl
            this.lbl_CutImage.Hide();

            //注：HotKeyId的合法取之范围是0x0000到0xBFFF之间，GlobalAddAtom函数得到的值在0xC000到0xFFFF之间，所以减掉0xC000来满足调用要求。
            this.hotKeyID = CommandAPI.WindowsAPI.GlobalAddAtom("Screenshot") - 0xc000;

            if (this.hotKeyID == 0)
            {
                this.hotKeyID = 0xBFFE;
            }

            if (this.hotKeyID == 0)
            {
                CommandAPI.WindowsAPI.RegisterHotKey(Handle, hotKeyID, (uint)KeyModifiers.Control | (uint)KeyModifiers.Alt, Keys.J);
            }
            else
            {
                CommandAPI.WindowsAPI.RegisterHotKey(Handle, hotKeyID, (uint)KeyModifiers.Control | (uint)KeyModifiers.Shift, Keys.J);
            }

        }

        /// <summary>
        /// 窗体关闭时取消注册热键
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if(e.CloseReason==CloseReason.ApplicationExitCall)
            {
                e.Cancel = false;
                CommandAPI.WindowsAPI.UnregisterHotKey(this.Handle, hotKeyID);
            }
            else
            {
                this.Hide();
                e.Cancel = true;
            }
        }

        /// <summary>
        /// 鼠标左键按下
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_MouseDown(object sender,MouseEventArgs e)
        {
            if(e.Button==MouseButtons.Left&&e.Clicks==1)
            {
                if(!this.lbl_CutImage.Visible)
                {
                    this.isCuting = true;
                    this.begainPoint = e.Location;
                    this.endPoint = e.Location;
                    SaveCutImageSize(e.Location, e.Location);

                    UpdateCutInfoLabel(UpdateUIMode.ShowCutImage | UpdateUIMode.ShowInfoBox);
                }
            }

            if (e.Button == MouseButtons.Left && e.Clicks == 2)
            {
                if (lbl_CutImage.Visible)
                {
                    ExecCutImage(false, false);
                }
            }

            if (e.Button == MouseButtons.Right)
            {
                ExitCutImage(!this.lbl_CutImage.Visible);
            }
        }

        /// <summary>
        /// 小图标退出
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmi_exit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        /// <summary>
        /// 鼠标移动
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            if(!lbl_CutImage.Visible)
            {
                UpdateCutInfoLabel(UpdateUIMode.None);
            }

            Point pntBgn = this.begainPoint;
            Point pntEnd = e.Location;

            if(pntEnd.X<pntBgn.X)
            {
                IsLeft = true;
            }

            if(pntEnd.Y<pntBgn.Y)
            {
                IsUp = true;
            }
            //if (e.Location.X < this.begainPoint.X && e.Location.Y < this.begainPoint.Y)
            //{
            //    pntBgn = e.Location;
            //    pntEnd = this.begainPoint;
            //}
            //else
            //{
            //    if (e.Location.X < this.begainPoint.X)
            //    {
            //        pntBgn = new Point(e.Location.X, this.begainPoint.Y);
            //        pntEnd = new Point(this.begainPoint.X, e.Location.Y);
            //    }
            //    else
            //    {
            //        if (e.Location.Y < this.begainPoint.Y)
            //        {
            //            pntBgn = new Point(this.begainPoint.X, e.Location.Y);
            //            pntEnd = new Point(e.Location.X, this.begainPoint.Y);
            //        }
            //    }
            //}

            if (this.isCuting)
            {
                SaveCutImageSize(pntBgn, pntEnd);
            }

            UpdateCutInfoLabel(UpdateUIMode.None);
        }

        /// <summary>
        /// 鼠标左键弹起
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (this.isCuting)
                {
                    this.isCuting = false;

                    UpdateCutInfoLabel(UpdateUIMode.None);
                }
            }

        }

        /// <summary>
        /// 选取截图区域绘制
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lbl_CutImage_Paint(object sender, PaintEventArgs e)
        {
            int imgWidth = this.lbl_CutImage.Width - 4;
            int imgHeight = this.lbl_CutImage.Height - 4;
            if (imgWidth < 1) { imgWidth = 1; }
            if (imgHeight < 1) { imgHeight = 1; }

            // 创建缓存图像，先将要绘制的内容全部绘制到缓存中，最后再一次性绘制到 Label 上，  
            // 这样可以提高性能，并且可以防止屏幕闪烁的问题  
            Bitmap bmp_lbl = new Bitmap(this.lbl_CutImage.Width, this.lbl_CutImage.Height);
            Graphics g = Graphics.FromImage(bmp_lbl);

            // 将要截取的部分绘制到缓存  
            Rectangle destRect = new Rectangle(2, 2, imgWidth, imgHeight);
            Point srcPoint = this.lbl_CutImage.Location;
            srcPoint.Offset(2, 2);
            Rectangle srcRect = new Rectangle(srcPoint, new System.Drawing.Size(imgWidth, imgHeight));
            g.DrawImage(this.screenImage, destRect, srcRect, GraphicsUnit.Pixel);

            
            SolidBrush brush = new SolidBrush(Color.FromArgb(10, 124, 202));
            Pen pen = new Pen(brush, 1.0F);

            //以下部分（边框和调整块）的绘制放在（编辑内容）的后面，是解决绘制编辑内容会覆盖（边框和调整块）的问题  

            // 绘制边框外的区域，解决会被编辑内容覆盖的问题  
            // 上边  
            destRect = new Rectangle(0, 0, this.lbl_CutImage.Width, 2);
            srcPoint = this.lbl_CutImage.Location;
            srcPoint.Offset(2, 2);
            srcRect = new Rectangle(srcPoint, new System.Drawing.Size(this.lbl_CutImage.Width, 2));
            g.DrawImage(this.BackgroundImage, destRect, srcRect, GraphicsUnit.Pixel);

            // 下边  
            destRect = new Rectangle(0, this.lbl_CutImage.Height - 2, this.lbl_CutImage.Width, 2);
            srcPoint = this.lbl_CutImage.Location;
            srcPoint.Offset(0, this.lbl_CutImage.Height - 2);
            srcRect = new Rectangle(srcPoint, new System.Drawing.Size(this.lbl_CutImage.Width, 2));
            g.DrawImage(this.BackgroundImage, destRect, srcRect, GraphicsUnit.Pixel);

            // 左边  
            destRect = new Rectangle(0, 2, 2, this.lbl_CutImage.Height - 4);
            srcPoint = this.lbl_CutImage.Location;
            srcPoint.Offset(0, 2);
            srcRect = new Rectangle(srcPoint, new System.Drawing.Size(2, this.lbl_CutImage.Height - 4));
            g.DrawImage(this.BackgroundImage, destRect, srcRect, GraphicsUnit.Pixel);

            // 右边  
            destRect = new Rectangle(this.lbl_CutImage.Width - 2, 2, 2, this.lbl_CutImage.Height - 4);
            srcPoint = this.lbl_CutImage.Location;
            srcPoint.Offset(this.lbl_CutImage.Width - 2, 2);
            srcRect = new Rectangle(srcPoint, new System.Drawing.Size(2, this.lbl_CutImage.Height - 4));
            g.DrawImage(this.BackgroundImage, destRect, srcRect, GraphicsUnit.Pixel);

            // 绘制边框  
            //g.DrawLine(pen, 2, 2, this.lbl_CutImage.Width + 3, 2);//下边
            //g.DrawLine(pen, 2, 2, 2, this.lbl_CutImage.Height - 3);//左边
            //g.DrawLine(pen, this.lbl_CutImage.Width - 3, 2, this.lbl_CutImage.Width + 3, this.lbl_CutImage.Height - 3);//右边
            //g.DrawLine(pen, 2, this.lbl_CutImage.Height - 3, this.lbl_CutImage.Width - 3, this.lbl_CutImage.Height - 3);//上边

            // 绘制四个角的调整块  
            //g.FillRectangle(brush, 0, 0, 4, 5);
            //g.FillRectangle(brush, this.lbl_CutImage.Width - 4, 0, 4, 5);
            //g.FillRectangle(brush, 0, this.lbl_CutImage.Height - 5, 4, 5);
            //g.FillRectangle(brush, this.lbl_CutImage.Width - 4, this.lbl_CutImage.Height - 5, 4, 5);

            // 绘制中间的四个调整块  
            //int blockX = this.lbl_CutImage.Width / 2 - 2;
            //int blockY = this.lbl_CutImage.Height / 2 - 2;
            //g.FillRectangle(brush, blockX, 0, 4, 5);
            //g.FillRectangle(brush, 0, blockY, 4, 5);
            //g.FillRectangle(brush, blockX, this.lbl_CutImage.Height - 5, 4, 5);
            //g.FillRectangle(brush, this.lbl_CutImage.Width - 4, blockY, 4, 5);

            // 绘制到 Label 上  
            e.Graphics.DrawImage(bmp_lbl, 0, 0);
            bmp_lbl.Dispose();
            
        }

        /// <summary>
        /// 截图选中区域双击保存截图
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lbl_CutImage_MouseDown(object sender, MouseEventArgs e)
        {
            // 左键双击事件  
            if (e.Button == MouseButtons.Left && e.Clicks == 2)
            {
                if (this.lbl_CutImage.Visible)
                {
                    ExecCutImage(false, false);
                }
            }
        }

        private void tsmi_Set_Click(object sender, EventArgs e)
        {
            frmSetup frm = new frmSetup(this.Handle);
            frm.ShowDialog();
        }
    }
}
